home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 1999 November / Macworld (1999-11).dmg / Shareware World / Comms & Internet / DXF to VRML97 1.0.1 / src / DropUNIX Lib / Lib Sources / DSUtils.c < prev   
Text File  |  1998-08-31  |  11KB  |  363 lines

  1. /******************************************************************************
  2. **
  3. **  Project Name:    DropShell
  4. **     File Name:    DSUtils.c
  5. **
  6. **   Description:    Utility routines that may be useful to DropBoxes
  7. **
  8. *******************************************************************************
  9. **                       A U T H O R   I D E N T I T Y
  10. *******************************************************************************
  11. **
  12. **    Initials    Name
  13. **    --------    -----------------------------------------------
  14. **    SCS            Stephan Somogyi
  15. **    LDR            Leonard Rosenthol
  16. **
  17. *******************************************************************************
  18. **                      R E V I S I O N   H I S T O R Y
  19. *******************************************************************************
  20. **
  21. **      Date        Author    Description
  22. **    ---------    ------    ---------------------------------------------
  23. **    23 Jun 94    LDR        Added a bunch of new routines for Marshall
  24. **    20 Feb 94    LDR        Added some new useful File System routines
  25. **    11 Dec 93    SCS        Universal Headers/UPPs (Phoenix 68k/PPC & PPCC)
  26. **                        Skipped System 6 compatible rev of DropShell source
  27. **                        Changed GetAppName to GetMyAppName (StdCLib conflict)
  28. **    12/09/91    LDR        Added the Apple event routines
  29. **    11/24/91    LDR        Original Version
  30. **
  31. ******************************************************************************/
  32.  
  33. #include <Dialogs.h>
  34. #include <Types.h>
  35. #include <SegLoad.h>
  36. #include <TextUtils.h>
  37.  
  38. #include "DSGlobals.h"
  39. #include "DSUtils.h"
  40.  
  41. /*
  42.     This routine is used to properly center an Alert before showing.
  43.     
  44.     It is per Human Interface specs by putting it in the top 1/3 of screen.
  45.     NOTE: This same technique can be used with DLOG resources as well.
  46. */
  47.  
  48. void CenterAlert ( short theID ) {
  49.     short        theX, theY;
  50.     AlertTHndl    theAlertHandle;
  51.     Rect        screen, alrt;
  52.     
  53.     theAlertHandle = (AlertTHndl) GetResource ( 'ALRT', theID );
  54.     if ( theAlertHandle != NULL ) {
  55.         HLock ((Handle) theAlertHandle );
  56.  
  57.         alrt = (*theAlertHandle)->boundsRect;
  58.         screen = qd.screenBits.bounds;
  59.         
  60.         theX = (( screen.right - screen.left ) - (alrt.right - alrt.left )) >> 1;
  61.         theY = (( screen.bottom - screen.top ) + GetMBarHeight () - (alrt.bottom - alrt.top)) >> 1;
  62.         theY -= ( screen.bottom - screen.top ) >> 2;    /* this moves it up for better viewing! */
  63.         OffsetRect ( &(*theAlertHandle)->boundsRect, theX - alrt.left, theY - alrt.top );
  64.     }
  65.         
  66.     SetCursor ( &qd.arrow );    // change this for code resources!
  67. }
  68.  
  69. /*
  70.     This routine is just a quick & dirty error reporter
  71. */
  72.  
  73. void _ErrorAlert ( short stringListID, short errorStringID, short osError, Str255 pFileName, short lineNumber ) {
  74.     #define    kAlertID    200
  75.     #define    kOSAlertID    201
  76.     Str255    errorString, lineNumberStr, osErrorString;
  77.  
  78.     NumToString ( lineNumber, lineNumberStr );
  79.     GetIndString ( errorString, stringListID, errorStringID );
  80.     
  81.     if (osError) {
  82.         NumToString (osError,  osErrorString);
  83.         ParamText ( errorString, pFileName, lineNumberStr, osErrorString );
  84.         CenterAlert ( kOSAlertID );
  85.         (void) Alert ( kOSAlertID, NULL );
  86.     } else {
  87.         ParamText ( errorString, pFileName, lineNumberStr, NULL );
  88.         CenterAlert ( kAlertID );
  89.         (void) Alert ( kAlertID, NULL );
  90.     }
  91. }
  92.  
  93. void _Panic ( short errorNumber, Str255 filename, short lineNumber) {
  94.  
  95.     _ErrorAlert(kErrorStringsID, errorNumber, 0, filename, lineNumber);
  96.     ExitToShell();
  97. }
  98.  
  99. void _FailOnError(OSErr err, short errorNumber, Str255 filename, short linenumber) {
  100.  
  101.     if (err != noErr) {
  102.         _ErrorAlert(kErrorStringsID, errorNumber, err, filename, linenumber);
  103.         ExitToShell();
  104.     }
  105. }
  106.  
  107. /*** These routines use the Process Manager to give you information about yourself ***/
  108.  
  109.  
  110. void GetMyAppName(Str255 appName)    {
  111.     OSErr                err;
  112.     ProcessInfoRec        info;
  113.     ProcessSerialNumber    curPSN;
  114.  
  115.     err = GetCurrentProcess(&curPSN);
  116.     
  117.     info.processInfoLength = sizeof(ProcessInfoRec);    // ALWAYS USE sizeof!
  118.     info.processName = appName;                            // so it returned somewhere
  119.     info.processAppSpec = NULL;                            // I don't care!
  120.  
  121.     err = GetProcessInformation(&curPSN, &info);
  122. }
  123.  
  124.  
  125. void GetAppFSSpec(FSSpec *appSpec)    {
  126.     OSErr                err;
  127.     Str255                appName;
  128.     ProcessInfoRec        info;
  129.     ProcessSerialNumber    curPSN;
  130.  
  131.     err = GetCurrentProcess(&curPSN);
  132.     
  133.     info.processInfoLength = sizeof(ProcessInfoRec);    // ALWAYS USE sizeof!
  134.     info.processName = appName;                            // so it returned somewhere
  135.     info.processAppSpec = appSpec;                        // so it can get returned!
  136.  
  137.     err = GetProcessInformation(&curPSN, &info);
  138. }
  139.  
  140. /* ••• File Routines begin here ••• */
  141. /*
  142.     This routine is used to force the Finder (as much as is possible) to update
  143.     information about a newly changed file or folder.  
  144.     It does this by changing the modification date of the surrounding folder.
  145. */
  146. OSErr ForceFinderUpdate(FSSpec *pFSS, Boolean flush)
  147. {
  148.     OSErr            lErr;
  149.     CInfoPBRec        lCBlk;
  150.     
  151.     if (pFSS->parID != 1)                            // if it's a vol then reuse the NameStr
  152.         lCBlk.dirInfo.ioNamePtr = 0L;
  153.     lCBlk.dirInfo.ioVRefNum = pFSS->vRefNum;        
  154.     lCBlk.dirInfo.ioDrDirID = pFSS->parID;
  155.     lCBlk.dirInfo.ioFDirIndex = 0;
  156.     lCBlk.dirInfo.ioCompletion = 0;
  157.  
  158.     lErr = PBGetCatInfoSync(&lCBlk);
  159.     if (!lErr) {
  160.         GetDateTime(&lCBlk.dirInfo.ioDrMdDat);
  161.         lCBlk.dirInfo.ioDrDirID = pFSS->parID;
  162.         lErr = PBSetCatInfoSync(&lCBlk);
  163.     
  164.         if ((!lErr) && (flush))
  165.             lErr = FlushVol(nil, pFSS->vRefNum);
  166.     }
  167.     
  168.     return (lErr);
  169. }
  170.  
  171. /*    Is the file in use (busy)? */
  172. Boolean FSpIsBusy(FSSpecPtr theFile)
  173. {
  174.     Boolean        isBusy = false;
  175.     OSErr        err;
  176.     CInfoPBRec    cipb;
  177.     
  178.     cipb.hFileInfo.ioCompletion    = 0L;
  179.     cipb.hFileInfo.ioNamePtr    = theFile->name;
  180.     cipb.hFileInfo.ioVRefNum    = theFile->vRefNum;
  181.     cipb.hFileInfo.ioFDirIndex    = 0;
  182.     cipb.hFileInfo.ioDirID        = theFile->parID;
  183.     err = PBGetCatInfoSync(&cipb);
  184.     if (!err) {
  185.         isBusy = (cipb.hFileInfo.ioFlAttrib & 0x80) == 0x80;    // bit 7 = either fork open
  186.     }
  187.     return(isBusy);
  188. }
  189.  
  190. /*    Is the “file” represented by this FSSpec really a folder? */
  191. Boolean    FSpIsFolder (FSSpecPtr theFSSpec) 
  192. {
  193.     OSErr    err;
  194.     CInfoPBRec    pb;
  195.     Str255    fName;
  196.     
  197.     if (theFSSpec->parID == fsRtParID)    // it's a volume!!
  198.         return(true);
  199.         
  200.     BlockMoveData (theFSSpec->name, fName, 32);
  201.     pb.hFileInfo.ioDirID        = theFSSpec->parID;
  202.     pb.hFileInfo.ioCompletion    = NULL;
  203.     pb.hFileInfo.ioNamePtr        = fName;
  204.     pb.hFileInfo.ioVRefNum        = theFSSpec->vRefNum;
  205.     pb.hFileInfo.ioFDirIndex    = 0;
  206.     pb.hFileInfo.ioFVersNum        = 0;
  207.     err = PBGetCatInfoSync(&pb);
  208.     
  209.     if (!err) {
  210.         if (pb.hFileInfo.ioFlAttrib & ioDirMask)
  211.             return(true);
  212.     }
  213.     return(false);
  214. }
  215.  
  216. /* ••• Apple event routines begin here ••• */
  217.  
  218. /*
  219.     This routine will create a targetDesc for sending to self.
  220.  
  221.     We take IM VI's advice and use the typePSN form with 
  222.     kCurrentProcess as the targetPSN.
  223. */
  224. OSErr GetTargetFromSelf (AEAddressDesc *targetDesc)
  225. {
  226.     ProcessSerialNumber    psn;
  227.  
  228.     psn.highLongOfPSN     = 0;
  229.     psn.lowLongOfPSN     = kCurrentProcess;
  230.  
  231.     return( AECreateDesc(typeProcessSerialNumber, (Ptr)&psn, sizeof(ProcessSerialNumber), targetDesc) );
  232. }
  233.  
  234. /*
  235.     This routine is the low level routine used by the SendODOCToSelf
  236.     routine.  It gets passed the list of files (in an AEDescList)
  237.     to be sent as the data for the 'odoc', builds up the event
  238.     and sends off the event.  
  239.  
  240.     It is broken out from SendODOCToSelf so that a SendODOCListToSelf could
  241.     easily be written and it could then call this routine - but that is left
  242.     as an exercise to the reader.
  243.     
  244.     Read the comments in the code for the order and details
  245. */
  246. void _SendDocsToSelf (AEDescList *aliasList)
  247. {
  248.     OSErr            err;
  249.     AEAddressDesc    theTarget;
  250.     AppleEvent        openDocAE, replyAE;
  251.  
  252. /*
  253.     First we create the target for the event.   We call another
  254.     utility routine for creating the target.
  255. */
  256.     err = GetTargetFromSelf(&theTarget);
  257.     if (err == noErr) {
  258.         /* Next we create the Apple event that will later get sent. */
  259.         err = AECreateAppleEvent(kCoreEventClass, kAEOpenDocuments, &theTarget, kAutoGenerateReturnID, kAnyTransactionID, &openDocAE);
  260.  
  261.         if (err == noErr) {
  262.             /* Now add the aliasDescList to the openDocAE */
  263.             err = AEPutParamDesc(&openDocAE, keyDirectObject, aliasList);
  264.  
  265.             if (err == noErr) {
  266.                 /*
  267.                     and finally send the event
  268.                     Since we are sending to ourselves, no need for reply.
  269.                 */
  270.                 err = AESend(&openDocAE, &replyAE, kAENoReply + kAECanInteract, kAENormalPriority, 3600, NULL, NULL);
  271.  
  272.                 /*
  273.                     NOTE: Since we are not requesting a reply, we do not need to
  274.                     need to dispose of the replyAE.  It is there simply as a 
  275.                     placeholder.
  276.                 */
  277.             }
  278.  
  279.         /*    
  280.             Dispose of the aliasList descriptor
  281.             We do this instead of the caller since it needs to be done
  282.             before disposing the AEVT
  283.         */
  284.             err = AEDisposeDesc(aliasList);
  285.         }
  286.  
  287.     /*and of course dispose of the openDoc AEVT itself*/
  288.         err = AEDisposeDesc(&openDocAE);
  289.     }
  290. }
  291.  
  292. /*
  293.     This is the routine called by SelectFile to send a single odoc to ourselves.
  294.     
  295.     It calls the above low level routine to do the dirty work of sending the AEVT -
  296.     all we do here is build a AEDescList of the file to be opened.
  297. */
  298. void SendODOCToSelf (FSSpec *theFileSpec) {
  299.  
  300.     OSErr        err;
  301.     AEDescList    aliasList;
  302.     AEDesc        aliasDesc;
  303.     AliasHandle    aliasH;
  304.     
  305.     /*Create the descList to hold the list of files*/
  306.     err = AECreateList(NULL, 0, false, &aliasList);
  307.  
  308.     if (err == noErr) {
  309.         /* First we setup the type of descriptor */
  310.         aliasDesc.descriptorType = typeAlias;
  311.  
  312.         /*
  313.             Now we add the file to descList by creating an alias and then
  314.             adding it into the descList using AEPutDesc
  315.         */
  316.         err = NewAlias(NULL, theFileSpec, &aliasH);
  317.         aliasDesc.dataHandle = (Handle)aliasH;
  318.         err = AEPutDesc(&aliasList, 0, &aliasDesc);
  319.         DisposeHandle((Handle)aliasH);
  320.  
  321.         /*Now call the real gut level routine to do the dirty work*/
  322.         _SendDocsToSelf(&aliasList);
  323.  
  324.         /*_SendDocsToSelf will dispose of aliasList for me*/
  325.     }
  326. }
  327.  
  328.  
  329. void SendQuitToSelf (void)
  330. {
  331.     OSErr            err;
  332.     AEAddressDesc    theTarget;
  333.     AppleEvent        quitAE, replyAE;
  334.  
  335. /*
  336.     First we create the target for the event.   We call another
  337.     utility routine for creating the target.
  338. */
  339.     err = GetTargetFromSelf(&theTarget);
  340.     if (err == noErr) {
  341.         /* Next we create the Apple event that will later get sent. */
  342.         err = AECreateAppleEvent(kCoreEventClass, kAEQuitApplication, &theTarget, kAutoGenerateReturnID, kAnyTransactionID, &quitAE);
  343.  
  344.         if (err == noErr) {
  345.             /*
  346.                 and finally send the event
  347.                 Since we are sending to ourselves, no need for reply.
  348.             */
  349.             err = AESend(&quitAE, &replyAE, kAENoReply + kAECanInteract, kAENormalPriority, 3600, NULL, NULL);
  350.  
  351.             /*
  352.                 NOTE: Since we are not requesting a reply, we do not need to
  353.                 need to dispose of the replyAE.  It is there simply as a 
  354.                 placeholder.
  355.             */
  356.         }
  357.  
  358.         /* and of course dispose of the quit AEVT itself */
  359.         err = AEDisposeDesc(&quitAE);
  360.     }
  361. }
  362.  
  363.